// using Godot;

// public enum GravityType
// {
//     Directional, // 定向推力 (风洞/牵引光束)
//     Attract,     // 黑洞 (吸向中心)
//     Repel        // 斥力场 (推离中心)
// }

// [Tool] // 允许在编辑器运行
// public partial class GravityPad : Area2D
// {
//     [ExportGroup("Dimensions")]
//     [Export]
//     public Vector2 PadSize
//     {
//         get => _padSize;
//         set { _padSize = value; UpdateDimensions(); }
//     }
//     private Vector2 _padSize = new Vector2(200, 100);

//     [ExportGroup("Settings")]
//     [Export] public bool IsActive = true;

//     // 修改 Type 的 Setter，切换类型时立即刷新视觉
//     [Export]
//     public GravityType Type
//     {
//         get => _type;
//         set { _type = value; UpdateDimensions(); }
//     }
//     private GravityType _type = GravityType.Directional;

//     [Export] public float ForcePower = 1500.0f;
//     [Export] public float PlayerMaxSpeed = 1000.0f;

//     [ExportGroup("Internal Refs")]
//     [Export] public CollisionShape2D Collider;
//     [Export] public GpuParticles2D Particles;
//     [Export] public NinePatchRect VisualFrame;

//     private PlayerController _playerInside = null;

//     public override void _Ready()
//     {
//         if (!Engine.IsEditorHint())
//         {
//             BodyEntered += OnBodyEntered;
//             BodyExited += OnBodyExited;
//         }
//         UpdateDimensions(); // 初始化一次
//     }

//     // --- 核心：尺寸更新逻辑 ---
//     private void UpdateDimensions()
//     {
//         // 1. 更新碰撞体大小
//         if (Collider != null)
//         {
//             // 确保资源唯一，防止改一个影响所有实例
//             if (Collider.Shape == null || !Collider.Shape.IsLocalToScene())
//             {
//                 var newShape = new RectangleShape2D();
//                 Collider.Shape = newShape;
//             }

//             if (Collider.Shape is RectangleShape2D rect)
//             {
//                 rect.Size = _padSize;
//             }
//         }

//         // 2. 更新视觉框大小 (NinePatchRect)
//         if (VisualFrame != null)
//         {
//             VisualFrame.Size = _padSize;
//             // 居中显示：位置 = 负的大小的一半
//             VisualFrame.Position = -_padSize / 2.0f;
//         }

//         // 3. 更新粒子发射范围 (Box Extents)
//         if (Particles != null && Particles.ProcessMaterial is ParticleProcessMaterial mat)
//         {
//             // 确保材质也是唯一的，否则所有重力场粒子会一起变
//             // 注意：Godot 4.x 中 ResourceLocalToScene 在编辑器里有时需要手动设置
//             // 这里我们动态调整 BoxExtents

//             mat.EmissionShape = ParticleProcessMaterial.EmissionShapeEnum.Box;
//             // BoxExtents 是“半长”，所以要除以 2
//             // Z轴设为1即可
//             mat.EmissionBoxExtents = new Vector3(_padSize.X / 2.0f, _padSize.Y / 2.0f, 1);

//             // 顺便调整粒子数量，让大区域粒子多，小区域粒子少（可选）
//             // int density = (int)((_padSize.X * _padSize.Y) / 4000.0f);
//             // Particles.Amount = Mathf.Clamp(density, 5, 100);
//         }
//         UpdateParticleVisuals();
//     }
//     private void UpdateParticleVisuals()
//     {
//         if (Particles == null) return;

//         // 显隐控制
//         Particles.Emitting = IsActive;
//         if (!IsActive) return;

//         // 获取材质 (必须是 ParticleProcessMaterial)
//         // 确保你在编辑器里给 Process Material 勾选了 "Local To Scene"！
//         if (Particles.ProcessMaterial is not ParticleProcessMaterial mat)
//         {
//             GD.PrintErr("GravityPad: 粒子材质必须是 ParticleProcessMaterial！");
//             return;
//         }

//         // --- 通用设置 ---
//         // 发射形状永远是 Box，覆盖整个区域
//         mat.EmissionShape = ParticleProcessMaterial.EmissionShapeEnum.Box;
//         mat.EmissionBoxExtents = new Vector3(_padSize.X / 2.0f, _padSize.Y / 2.0f, 1);

//         // 粒子数量根据面积自动计算 (密度控制)
//         int density = (int)((_padSize.X * _padSize.Y) / 4000.0f);
//         Particles.Amount = Mathf.Clamp(density, 5, 100);
//         // 这是一个坑：修改 Amount 后必须重置粒子才能生效，但在 Tool 模式下频繁 Reset 会闪烁
//         // 暂时不强制 Reset，或者你可以只在 density 变化很大时调用 Particles.Restart();

//         // --- 根据重力类型调整运动方向 ---
//         switch (Type)
//         {
//             case GravityType.Directional:
//                 // 1. 重置径向加速度 (防止之前的设置残留)
//                 mat.RadialAccelMin = 0;
//                 mat.RadialAccelMax = 0;

//                 // 2. 设置线性速度 (沿着 X 轴)
//                 mat.Direction = Vector3.Right; // (1, 0, 0)
//                 mat.Spread = 0; // 0度，完全平行直线
//                 mat.Gravity = Vector3.Zero; // 无重力下落
//                 mat.InitialVelocityMin = 100;
//                 mat.InitialVelocityMax = 150;

//                 // 3. 颜色提示 (可选)：白色/青色代表风
//                 Particles.Modulate = Colors.White;
//                 break;

//             case GravityType.Attract: // 吸引 (黑洞)
//                 // 1. 关掉线性速度
//                 mat.InitialVelocityMin = 0;
//                 mat.InitialVelocityMax = 0;
//                 mat.Gravity = Vector3.Zero;

//                 // 2. 开启负向径向加速度 (吸向中心)
//                 // 数值越大，吸得越快
//                 mat.RadialAccelMin = -100;
//                 mat.RadialAccelMax = -200;

//                 // 3. 颜色提示：紫色代表引力
//                 Particles.Modulate = Colors.Magenta;
//                 break;

//             case GravityType.Repel: // 排斥 (斥力场)
//                 // 1. 关掉线性速度
//                 mat.InitialVelocityMin = 0;
//                 mat.InitialVelocityMax = 0;
//                 mat.Gravity = Vector3.Zero;

//                 // 2. 开启正向径向加速度 (推离中心)
//                 mat.RadialAccelMin = 100;
//                 mat.RadialAccelMax = 200;

//                 // 3. 颜色提示：橙色代表斥力
//                 Particles.Modulate = Colors.Orange;
//                 break;
//         }
//     }


//     public override void _PhysicsProcess(double delta)
//     {
//         if (Engine.IsEditorHint()) return;
//         if (!IsActive || _playerInside == null) return;

//         ApplyForce((float)delta);
//     }


//     private void ApplyForce(double delta)
//     {
//         Vector2 forceDirection = Vector2.Zero;




//         switch (Type)
//         {
//             case GravityType.Directional:
//                 // 现在的方向完全取决于节点的旋转
//                 // Transform.X 是节点的右方，Transform.Y 是下方
//                 forceDirection = Transform.X;
//                 break;

//             case GravityType.Attract:
//                 // 指向中心
//                 forceDirection = (GlobalPosition - _playerInside.GlobalPosition).Normalized();
//                 break;

//             case GravityType.Repel:
//                 // 背离中心
//                 forceDirection = (_playerInside.GlobalPosition - GlobalPosition).Normalized();
//                 break;
//         }

//         // 计算最终的加速度向量
//         Vector2 finalForce = forceDirection * ForcePower;

//         //判断 玩家与 加速度向量方向的分量大小
//         Vector2 playerVelocity = _playerInside.GetVelocity();
//         float velocityAlongForce = playerVelocity.Dot(finalForce.Normalized());
//         // 如果玩家速度已经超过加速度的大小，且方向相同，则不再施加加速度
//         if (velocityAlongForce >= PlayerMaxSpeed)
//         {
//             return;
//         }


//         // 调用玩家的方法叠加速度
//         _playerInside.AddExternalVelocity(finalForce, delta);

//         // 直接叠加速度


//     }

//     private void OnBodyEntered(Node2D body)
//     {
//         if (IsActive && (body is PlayerController player))
//         {
//             _playerInside = player;

//         }
//     }

//     private void OnBodyExited(Node2D body)
//     {
//         if (body is PlayerController player && player == _playerInside)
//         {
//             _playerInside = null;

//         }
//     }



//     private void UpdateVisuals()
//     {
//         if (Particles != null) Particles.Emitting = IsActive;
//         if (VisualFrame != null) VisualFrame.Visible = IsActive;
//     }
// }


using Godot;
using System.Collections.Generic; // 需要引入 List

public enum GravityType
{
    Directional,
    Attract,
    Repel
}

[Tool]
public partial class GravityPad : Area2D
{
    [ExportGroup("Dimensions")]
    [Export]
    public Vector2 PadSize
    {
        get => _padSize;
        set { _padSize = value; UpdateDimensions(); }
    }
    private Vector2 _padSize = new Vector2(200, 100);

    [ExportGroup("Settings")]
    [Export] public bool IsActive = true;

    [Export]
    public GravityType Type
    {
        get => _type;
        set { _type = value; UpdateDimensions(); }
    }
    private GravityType _type = GravityType.Directional;

    [Export] public float ForcePower = 1500.0f;
    [Export] public float MaxSpeed = 1000.0f; // 改个名，因为对箱子也生效

    [ExportGroup("Internal Refs")]
    [Export] public CollisionShape2D Collider;
    [Export] public GpuParticles2D Particles;
    [Export] public NinePatchRect VisualFrame;

    // --- 修改点 1: 改为列表存储 ---
    // 存储所有实现了接口的 Node2D
    private List<Node2D> _affectedBodies = new List<Node2D>();

    public override void _Ready()
    {
        if (!Engine.IsEditorHint())
        {
            BodyEntered += OnBodyEntered;
            BodyExited += OnBodyExited;
        }
        UpdateDimensions();
    }

    private void UpdateDimensions()
    {
        if (Collider != null)
        {
            if (Collider.Shape == null || !Collider.Shape.IsLocalToScene())
            {
                var newShape = new RectangleShape2D();
                Collider.Shape = newShape;
            }
            if (Collider.Shape is RectangleShape2D rect) rect.Size = _padSize;
        }

        if (VisualFrame != null)
        {
            VisualFrame.Size = _padSize;
            VisualFrame.Position = -_padSize / 2.0f;
        }

        if (Particles != null && Particles.ProcessMaterial is ParticleProcessMaterial mat)
        {
            mat.EmissionShape = ParticleProcessMaterial.EmissionShapeEnum.Box;
            mat.EmissionBoxExtents = new Vector3(_padSize.X / 2.0f, _padSize.Y / 2.0f, 1);
        }
        UpdateParticleVisuals();
    }

    private void UpdateParticleVisuals()
    {
        if (Particles == null) return;
        Particles.Emitting = IsActive;
        if (!IsActive) return;

        if (Particles.ProcessMaterial is not ParticleProcessMaterial mat) return;

        mat.EmissionShape = ParticleProcessMaterial.EmissionShapeEnum.Box;
        mat.EmissionBoxExtents = new Vector3(_padSize.X / 2.0f, _padSize.Y / 2.0f, 1);

        int density = (int)((_padSize.X * _padSize.Y) / 4000.0f);
        Particles.Amount = Mathf.Clamp(density, 5, 100);

        switch (Type)
        {
            case GravityType.Directional:
                mat.RadialAccelMin = 0; mat.RadialAccelMax = 0;
                mat.Direction = Vector3.Right;
                mat.Spread = 0;
                mat.Gravity = Vector3.Zero;
                mat.InitialVelocityMin = 100; mat.InitialVelocityMax = 150;
                Particles.Modulate = Colors.White;
                break;

            case GravityType.Attract:
                mat.InitialVelocityMin = 0; mat.InitialVelocityMax = 0;
                mat.Gravity = Vector3.Zero;
                mat.RadialAccelMin = -100; mat.RadialAccelMax = -200;
                Particles.Modulate = Colors.Magenta;
                break;

            case GravityType.Repel:
                mat.InitialVelocityMin = 0; mat.InitialVelocityMax = 0;
                mat.Gravity = Vector3.Zero;
                mat.RadialAccelMin = 100; mat.RadialAccelMax = 200;
                Particles.Modulate = Colors.Orange;
                break;
        }
    }

    public override void _PhysicsProcess(double delta)
    {
        if (Engine.IsEditorHint()) return;
        if (!IsActive || _affectedBodies.Count == 0) return;

        ApplyForce((float)delta);
    }

    // --- 修改点 2: 遍历列表处理物理 ---
    private void ApplyForce(double delta)
    {
        // 倒序遍历，以防在遍历过程中有物体被销毁导致报错
        for (int i = _affectedBodies.Count - 1; i >= 0; i--)
        {
            var body = _affectedBodies[i];

            // 安全检查：如果物体被销毁了，从列表移除
            if (!IsInstanceValid(body))
            {
                _affectedBodies.RemoveAt(i);
                continue;
            }

            // 强转为接口进行操作
            if (body is IGravityTarget target)
            {
                Vector2 forceDirection = Vector2.Zero;

                switch (Type)
                {
                    case GravityType.Directional:
                        forceDirection = Transform.X;
                        break;
                    case GravityType.Attract:
                        forceDirection = (GlobalPosition - body.GlobalPosition).Normalized();
                        break;
                    case GravityType.Repel:
                        forceDirection = (body.GlobalPosition - GlobalPosition).Normalized();
                        break;
                }

                Vector2 finalForce = forceDirection * ForcePower;

                // 速度限制检查
                Vector2 bodyVelocity = target.GetVelocity();
                float velocityAlongForce = bodyVelocity.Dot(finalForce.Normalized());

                if (velocityAlongForce < MaxSpeed)
                {
                    target.AddExternalVelocity(finalForce, delta);
                }
            }
        }
    }

    // --- 修改点 3: 进出区域逻辑 ---
    private void OnBodyEntered(Node2D body)
    {
        // 只要实现了 IGravityTarget 接口，不管是 Player 还是 Box 统统收进来
        if (IsActive && body is IGravityTarget)
        {
            if (!_affectedBodies.Contains(body))
            {
                _affectedBodies.Add(body);
            }
        }
    }

    private void OnBodyExited(Node2D body)
    {
        if (_affectedBodies.Contains(body))
        {
            _affectedBodies.Remove(body);
        }
    }

    private void UpdateVisuals()
    {
        if (Particles != null) Particles.Emitting = IsActive;
        if (VisualFrame != null) VisualFrame.Visible = IsActive;
    }
}